﻿/*  CLR版本: 4.0.30319.18063
 * 系统时间: 2014/10/31 14:20:43
 * 创建年份: 2014
 *     作者: 程炜.Snail
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Quick.Communicator
{
    public abstract class IResolver
    {
        /// <summary>
        /// 通讯编码格式提供者,为通讯服务提供编码和解码服务
        /// 可以在继承类中定制自己的编码方式如:数据加密传输等
        /// </summary>
        [Serializable]
        public class ResolverCoder
        {
            private System.Text.Encoding _Encoding;
            /// <summary>
            /// 报文编码
            /// </summary>
            public System.Text.Encoding Encoding
            {
                get { return _Encoding; }
                set { _Encoding = value; }
            }
            /// <summary>
            /// 默认的构造函数,采用操作系统当前的 ANSI 代码页编码
            /// </summary>
            public ResolverCoder()
            {
                _Encoding = Encoding.Default;
            }
            /// <summary>
            /// 采用指定的代码页名称对应的编码
            /// </summary>
            /// <param name="coderStr"></param>
            public ResolverCoder(string coderStr)
            {
                _Encoding = System.Text.Encoding.GetEncoding(coderStr);
            }
            /// <summary>
            /// 采用指定的编码
            /// </summary>
            /// <param name="encoding"></param>
            public ResolverCoder(System.Text.Encoding encoding)
            {
                _Encoding = encoding;
            }
            /// <summary>
            /// 通讯数据解码
            /// </summary>
            /// <param name="dataBytes">需要解码的数据</param>
            /// <returns>编码后的数据</returns>
            public virtual string GetEncodingString(byte[] dataBytes, int size)
            {
                return this._Encoding.GetString(dataBytes, 0, size);
            }
            /// <summary>
            /// 数据编码
            /// </summary>
            /// <param name="datagram">需要编码的报文</param>
            /// <returns>编码后的数据</returns>
            public virtual byte[] GetEncodingBytes(string datagram)
            {
                return this._Encoding.GetBytes(datagram);
            }
        }
        /// <summary>
        /// Hex String 需要去除头尾的 ',',' '
        /// </summary>
        protected char[] m_HexStringTrimCharArray = new char[] { ',', ' ' };
        /// <summary>
        /// 报文结束标记
        /// </summary>
        protected string m_EndTag = string.Empty;
        /// <summary>
        /// 报文格式
        /// </summary>
        protected ResolverCoder m_Coder;
        /// <summary>
        /// 获取报文解析编码
        /// </summary>
        public Encoding Encoding
        {
            get
            {
                return m_Coder.Encoding;
            }
        }
        /// <summary>
        /// 返回结束标记(字符串)
        /// </summary>
        public string EndTag
        {
            get { return m_EndTag; }
        }
        protected string m_HexStringEndTag;
        /// <summary>
        /// 经过字节字符编码的 结束标记 (16进制 ,分隔) 的字符串
        /// </summary>
        public string HexStringEndTag
        {
            set
            {
                m_HexStringEndTag = value;
            }
            get
            {
                if (!string.IsNullOrEmpty(m_HexStringEndTag))
                {
                    return m_HexStringEndTag;
                }
                else
                {
                    if (string.IsNullOrEmpty(this.m_EndTag))
                    {
                        return string.Empty;
                    }
                    m_HexStringEndTag = ByteToHexString(this.m_Coder.GetEncodingBytes(this.m_EndTag));
                    return m_HexStringEndTag;
                }
            }
        }
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public IResolver()
        {
            this.m_Coder = new ResolverCoder();
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="coder">字符编码</param>
        public IResolver(string coder)
        {
            this.m_Coder = new ResolverCoder(coder);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="coder">字符编码</param>
        public IResolver(System.Text.Encoding coder)
        {
            this.m_Coder = new ResolverCoder(coder);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="coder">字符编码</param>
        /// <param name="endTag">报文结束符</param>
        /// <param name="endTagIsHex">结束符是否是Hex格式</param>
        public IResolver(string coder, string endTag, bool endTagIsHex = false)
        {
            this.m_Coder = new ResolverCoder(coder);
            this.m_EndTag = endTag;
            if (endTagIsHex)
            {
                this.m_HexStringEndTag = endTag;
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="coder">字符编码</param>
        /// <param name="endTag">报文结束符</param>
        /// <param name="endTagIsHex">结束符是否是Hex格式</param>
        public IResolver(System.Text.Encoding coder, string endTag, bool endTagIsHex = false)
        {
            this.m_Coder = new ResolverCoder(coder);
            this.m_EndTag = endTag;
            if (endTagIsHex)
            {
                this.m_HexStringEndTag = endTag;
            }
        }
        /// <summary>
        /// 设置字符编码类型
        /// </summary>
        /// <param name="encoding">字符编码</param>
        public virtual void SetResolverCoder(System.Text.Encoding encoding)
        {
            this.m_Coder.Encoding = encoding;
        }
        /// <summary>
        /// 设置报文结束符
        /// </summary>
        /// <param name="endTag">报文结束符</param>
        /// <param name="endTagIsHex">结束符是否是Hex格式</param>
        public virtual void SetResolverEndTag(string endTag, bool endTagIsHex = false)
        {
            this.m_EndTag = endTag;
            if (endTagIsHex)
            {
                this.m_HexStringEndTag = endTag;
            }
        }
        /// <summary>
        /// 解析报文
        /// (使用','分隔的 hexString)
        /// </summary>
        /// <param name="rawDatagram">原始数据(使用','分隔的 hexString),返回未使用的报文片断,该片断会保存在Session的Datagram对象中</param>
        /// <returns>报文数组(使用','分隔的 hexString),原始数据可能包含多个报文</returns>
        public virtual string[] Resolve(ref string rawDatagram)
        {
            ArrayList datagrams = new ArrayList();
            //末尾标记位置索引
            int tagIndex = -1;
            while (true)
            {
                //在进行数据分包的时候,忽略大小写进行比较
                tagIndex = rawDatagram.IndexOf(this.HexStringEndTag, StringComparison.OrdinalIgnoreCase);

                if (tagIndex == -1)
                {
                    break;
                }
                else
                {
                    //按照末尾标记把字符串分为左右两个部分
                    string newDatagram = rawDatagram.Substring(0, tagIndex).Trim(m_HexStringTrimCharArray);
                    if (!string.IsNullOrEmpty(newDatagram))
                    {
                        //添加不包含结束符的 hexString
                        datagrams.Add(newDatagram);
                    }
                    if (tagIndex + this.HexStringEndTag.Length >= rawDatagram.Length)
                    {
                        rawDatagram = string.Empty;
                        break;
                    }
                    rawDatagram = rawDatagram.Substring(tagIndex + this.HexStringEndTag.Length);
                    //从开始位置开始查找
                    tagIndex = -1;
                }
            }
            string[] results = new string[datagrams.Count];
            datagrams.CopyTo(results);
            return results;
        }
        /// <summary> 
        /// 字节数组转16进制字符串
        /// 使用 , 进行分割
        /// </summary> 
        /// <param name="bytes"></param> 
        /// <returns></returns> 
        public string ByteToHexString(byte[] bytes, char splitChar = ',')
        {
            System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    if (strBuilder.Length > 0)
                    {
                        strBuilder.Append(splitChar);
                    }
                    strBuilder.Append(bytes[i].ToString("X2"));
                }
            }
            return strBuilder.ToString();
        }
        /// <summary> 
        /// 字符串转16进制字节数组
        /// </summary> 
        /// <param name="hexString">使用 , 分割16进制字符的字符串</param> 
        /// <returns></returns> 
        public byte[] HexStringToByte(string hexString)
        {
            if (string.IsNullOrEmpty(hexString))
            {
                return null;
            }
            //如果头尾字符是 , 则删除这些逗号
            hexString = hexString.Trim(m_HexStringTrimCharArray);
            if (string.IsNullOrEmpty(hexString))
            {
                return null;
            }
            string[] hexStringArray = hexString.Split(m_HexStringTrimCharArray);
            byte[] returnBytes = new byte[hexStringArray.Length];
            for (int i = 0; i < hexStringArray.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(hexStringArray[i], 16);
            }
            hexStringArray = null;
            return returnBytes;
        }
        /// <summary>
        /// 将报文进行编码,并且增加报文结束符
        /// </summary>
        /// <param name="rawDatagram">不包含报文结束符的报文</param>
        /// <returns>带结束符的报文字节数组</returns>
        public virtual byte[] DatagramEncoding(string rawDatagram)
        {
            byte[] bt = DatagramEncodingBarringEngTag(rawDatagram);
            byte[] btEndTag = HexStringToByte(this.HexStringEndTag);
            if (null == btEndTag || btEndTag.Length < 1)
            {   //如果不存在报文结束符, 则直接返回
                return bt;
            }
            else
            {
                List<byte> list = new List<byte>();
                list.AddRange(bt);
                list.AddRange(btEndTag);
                return list.ToArray();
            }
        }
        /// <summary>
        /// 将报文进行编码,不增加报文结束符
        /// </summary>
        /// <param name="rawDatagram">不包含报文结束符的报文</param>
        /// <returns>报文字节数组(不增加报文结束符)</returns>
        public virtual byte[] DatagramEncodingBarringEngTag(string rawDatagram)
        {
            return this.m_Coder.GetEncodingBytes(rawDatagram);
        }
        /// <summary>
        /// 将字节报文解码成字符串
        /// 返回不带结束符的报文字符串
        /// </summary>
        /// <param name="bytes">不包含报文结束符的报文字节数组</param>
        /// <returns>不带结束符的报文字符串</returns>
        public virtual string DatagramDesEncoding(byte[] bytes)
        {
            if (null == bytes)
            {
                return string.Empty;
            }
            return this.m_Coder.GetEncodingString(bytes, bytes.Length);
        }
        /// <summary>
        /// 在报文字节数组后增加报文结束符
        /// 方法会自动判断是否存在结束符,如果没有,则返回原数据
        /// </summary>
        /// <returns>带结束符的报文字节数组</returns>
        public virtual byte[] DatagramAddEndTag(byte[] bytes)
        {
            if (string.IsNullOrEmpty(this.m_EndTag) && string.IsNullOrEmpty(this.m_HexStringEndTag))
            {
                return bytes;
            }
            else
            {
                return this.HexStringToByte(string.Concat(this.ByteToHexString(bytes), ",", this.HexStringEndTag));
            }
        }
    }
}
